<?php

namespace app\api\service;

use think\facade\Cache;
use app\model\User;
use app\common\Common;
use app\model\Applet;
use app\model\EchoRuleConfig;
use app\model\OfficialAccounts;
use app\model\Link;
use app\model\UserLoginRecord;
use think\facade\Log;

/**
 * 登录服务类
 */
class LoginService
{
    private $model;
    private $officialAccountsModel;
    private $appletModel;
    private $linkModel;
    private $userLoginRecordModel;
    private $EchoRuleConfigModel;
    public function __construct(User $model, OfficialAccounts $officialAccountsModel, Applet $appletModel, Link $linkModel, UserLoginRecord $userLoginRecordModel,EchoRuleConfig $echoRuleConfig)
    {
        $this->model = $model;
        $this->officialAccountsModel = $officialAccountsModel;
        $this->appletModel = $appletModel;
        $this->linkModel = $linkModel;
        $this->userLoginRecordModel = $userLoginRecordModel;
        $this->EchoRuleConfigModel = $echoRuleConfig;
    }

    /**
     * 用户登录
     * 
     * @dateTime 2022/09/01
     * @author zhixiang0215@126.com
     * @param array params
     * @return array
     */
    public function userLogin(array $params, array $header)
    {
        $redis = Cache::store('redis')->handler();
        $key = config('redis_key.api.user_login');
        $linkIdKey = config('redis_key.api.user_login_link_id');
        $expire = config('redis_key.api.user_login_expire');
        $expireTime = time() + $expire;

        $appId = $params['app_id'];
        $appletData = $this->appletModel->getInfoByWhere(['app_id' => $appId], 'app_secret');
        $secret = $appletData['app_secret'];
        $code = $params['code'];

        $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$appId.'&secret='.$secret.'&js_code='.$code.'&grant_type=authorization_code';
        $result = Common::_curl($url, '', 'GET', ['json' => 'Accept: application/json']);

        $data = json_decode($result, true);

        if (empty($data['openid']) || !empty($data['errcode'])) {
            return [];
        }

        if (!empty($params['uid']) && !empty($params['official_account_id']) && empty($params['link_id'])) {
            // 通过公众号进入
            $userData = self::officialAccountEnter($params, $data['openid']);
            $params['ip'] = Common::getClientIp();

        } else if (!empty($params['link_id'])) {
            // 通过链接进入
            $userData = self::linkEnter($params, $data['openid']);
            $params['ip'] = $userData['ip'];
            $params['ua'] = $userData['ua'];
            $params['advertiser_id'] = $userData['advertiser_id'];
            $params['clickid'] = $userData['clickid'];
        } else {
            // 直接进入小程序
            $userData = self::appletEnter($params, $data['openid']);
            $params['ip'] = Common::getClientIp();
        }

        if($userData['is_delete'] === 1){
           return [];
        }

        $params['open_id'] = $data['openid'];
        unset($params['code']);
        $params['id'] = $userData['uid'];
        $token = Common::createToken($userData['uid']);

        $params['is_online'] = config('enum.type');
        $params['expire_time'] = $expireTime;
        $params['token'] = $token;
        $params['link_id'] = $userData['link_id'];
        $params['official_account_id'] = $userData['official_account_id'];
        $params['user_name'] = $userData['user_name'];
        $params['avatar'] = $userData['avatar'];
        $params['status'] = $userData['status'];
        $params['session_key'] = $data['session_key'] ?? '';

        // 判断今天是否已签到
        if (!empty($userData['sign_time'])) {
            $currentSignTime = strtotime(date('Y-m-d', time()));
            $lastSignTime = strtotime(date('Y-m-d', $userData['sign_time']));
            if ($currentSignTime == $lastSignTime) {
                $params['sign_status'] = 1;
            } else {
                $params['sign_status'] = 0;
            }
        } else {
            $params['sign_status'] = 0;
        }
        if (!empty($params['link_id'])) {
            $redis->select(7);
            $redis->set('link_id_status'.$userData['uid'].'-'.$appId, 1, $expire);
        }else{
            $redis->select(7);
            $redis->set('link_id_status'.$userData['uid'].'-'.$appId, 0, $expire);
        }
        $redis->select(8);
        $boolUserId = $redis->set($token, $userData['uid'], $expire);
        if ($userData['link_id']) {
            $redis->set($linkIdKey . $token, $userData['link_id'], $expire);
        }
  
        $boolUser = $redis->set($key . $userData['uid'], json_encode($params), $expire);

        if (empty($boolUserId) || empty($boolUser)) {
            return [];
        }

        $this->userLoginRecordModel->edit([
            'uid' => $userData['uid'],
            'date' => date('Ymd'),
            'month' => date('Ym'),
            'ip' => Common::getClientIp(),
            'created_at' => time(),
            'official_account_id' => $userData['official_account_id'],
            'link_id' => !empty($userData['link_id']) ? $userData['link_id'] : null
        ]);

        return $params;
    }

    // 通过公众号进入
    public function officialAccountEnter(array $params, string $openId)
    {
        $userInfo = $this->model->getInfoById($params['uid'], 'id, is_delete, official_account_id, applet_id, link_id, register_date, created_at, sign_time, official_account_open_id, interpolate_id, user_name, avatar, status');

        $officialAccountData = $this->officialAccountsModel->getInfoById($userInfo['official_account_id'], 'applet_id');

        $saveData = [
            'id' => $params['uid'],
            'open_id' => $openId,
            'last_login_time' => time(),
            'applet_id' => $officialAccountData['applet_id'],
            'user_name' => empty($params['user_name']) ? '' : $params['user_name'],
            'avatar' => empty($params['avatar']) ? '' : $params['avatar'],
            'source' => 3,
            'mobile_system' => empty($params['mobile_system']) ? null : $params['mobile_system'],
        ];

        if (empty($userInfo['register_date'])) {
            $saveData['register_date'] = date('Ymd');
        }
        if (empty($userInfo['created_at'])) {
            $saveData['created_at'] = time();
        }

        $uid = $this->model->edit($saveData);
        return [
            'uid' => $uid,
            'link_id' => !empty($userInfo['link_id']) ? $userInfo['link_id'] : '',
            'official_account_id' => $userInfo['official_account_id'],
            'sign_time' => !empty($userInfo) ? $userInfo['sign_time'] : null,
            'official_account_open_id' => $userInfo['official_account_open_id'],
            'interpolate_id' => $userInfo['interpolate_id'],
            'user_name' => empty($userInfo['user_name']) ? '' : $userInfo['user_name'],
            'avatar' => empty($userInfo['avatar']) ? '' : $userInfo['avatar'],
            'status' => !empty($userInfo['status']) ? $userInfo['status'] : 0,
            'is_delete' => !empty($userInfo['is_delete']) ? $userInfo['is_delete'] : 0
        ];
    }

    // 通过链接进入
    public function linkEnter(array $params, string $openId)
    {
        $where = [
            'open_id' => $openId,
            'link_id' => $params['link_id']
        ];
        $fields = 'id, is_delete, official_account_id, applet_id, link_id, register_date, created_at, sign_time, official_account_open_id, interpolate_id, user_name, avatar, status';

        $userInfo = $this->model->getDataByWhere($where, $fields);

        $appletData = $this->appletModel->getInfoByWhere(['app_id' => $params['app_id']],'id,name');

        if (!$userInfo) {
            // 通过链接id对应的公众号查找数据
            $linkData = $this->linkModel->getInfoByWhere(['id' => $params['link_id']], 'official_account_id, echo_rule_config_id, token, advertiser_id');
            $userInfo = $this->model->getDataByWhere(['official_account_id' => $linkData['official_account_id'], 'open_id' => $openId], $fields, 'last_login_time desc');

            if (!$userInfo) {
                $saveData = [
                    'open_id' => $openId,
                    'official_account_id' => $linkData['official_account_id'],
                    'applet_id' => $appletData['id'],
                    'link_id' => $params['link_id'],
                    'activation_time' => date('Y-m-d H:i:s'),
                    'last_login_time' => time(),
                    'register_date' => date('Ymd'),
                    'created_at' => time(),
                    'source' => 1,
                    'mobile_system' => empty($params['mobile_system']) ? null : $params['mobile_system'],
                ];
            } else {
                $saveData = [
                    'id' => $userInfo['id'],
                    'open_id' => $openId,
                    'link_id' => $params['link_id'],
                    'activation_time' => date('Y-m-d H:i:s'),
                    'last_login_time' => time(),
                    'mobile_system' => empty($params['mobile_system']) ? null : $params['mobile_system'],
                ];
            }

        } else {
            $saveData = [
                'id' => $userInfo['id'],
                'last_login_time' => time(),
                'activation_time' => date('Y-m-d H:i:s'),
                'link_id' => $params['link_id'],
                'mobile_system' => empty($params['mobile_system']) ? null : $params['mobile_system'],
            ];
        }

        $redis = Cache::store('redis')->handler();
        $redis->select(6);

        $linkData = $this->linkModel->getInfoByWhere(['id' => $params['link_id']], 'official_account_id, echo_rule_config_id, token, is_capitalization, advertiser_id');

        $ip = empty($params['ip']) ? '' : $params['ip'];
        $ua = empty($params['ua']) ? '' : $params['ua'];
        
        $advertiserId = '';
        $clickid = !empty($params['bd_vid']) ? $params['bd_vid'] : '';

        if (!empty($params['type']) && $params['type'] == 3) {
            // 百度激活回传
            $ip = $_SERVER['REMOTE_ADDR'];
            $bool = strpos($_SERVER['HTTP_USER_AGENT'], 'Android');
            
            if ($bool) {
                // Android
                $regx = '/Build(.*?)\; /is';
                preg_match($regx, $_SERVER['HTTP_USER_AGENT'], $match);

                $userAgent = $match[1];
            } else {
                // iOS
                $regx = '/\((.*?)\)/';
                preg_match($regx, $_SERVER['HTTP_USER_AGENT'], $match);
                $userAgent = $match[1];
            }
            $ua = strtoupper(str_replace(' ', '', $userAgent));
            
            $saveData['ip'] = $ip;
            $saveData['ua'] = $ua;
            $monitoringData = $redis->get(md5($clickid.$params['link_id']));
            if (empty($monitoringData)) {
                $monitoringData = $redis->get(md5($ip.$ua.$params['link_id']));
            }

            $monitoringData = json_decode($monitoringData, true);

            if (!empty($monitoringData['advertiser_id'])) {
                $saveData['advertiser_id'] = $monitoringData['advertiser_id'];
                $advertiserId = $monitoringData['advertiser_id'];
            }

            if (empty($linkData)) {
                $linkData = $this->linkModel->getInfoByWhere(['id' => $params['link_id']], 'official_account_id, echo_rule_config_id, token, advertiser_id');
            }
            if (!empty($linkData['token']) && $clickid) {
                $url = 'https://ocpc.baidu.com/ocpcapi/api/uploadConvertData';
                $conversionTypes = [
                    'logidUrl' => 'https://'.$_SERVER['SERVER_NAME'].'?bd_vid='.$clickid,
                    'newType' => 49,
                ];

                $datas = ['token' => $linkData['token'], 'conversionTypes' => $conversionTypes];
                $requestData = json_encode($datas);
                $result = Common::curlRequest($url, 'POST', $requestData, ['Content-Type : application/json']);
            }
            $saveData['clickid'] = $clickid;

        } else if (!empty($params['type']) && $params['type'] == 4) {
            // 腾讯激活回传
            $monitoringData = $redis->get(md5($openId));
            if (!empty($monitoringData)) {
                $monitoringData = json_decode($monitoringData, true);
                $url = urldecode($monitoringData['callback']);
                $requestData = [
                    'actions' => [[
                        'action_time' => time(),
                        'user_id' => [
                            'wechat_openid' => $openId,
                            'wechat_app_id' => $params['app_id']
                        ],
                        'trace' => [
                            'click_id' => $monitoringData['click_id']
                        ],
                        'action_type' => 'REGISTER'
                    ]]
                ];

                $result = Common::curlRequest($url, 'POST', json_encode($requestData), ['Content-Type: application/json']);
                $saveData['clickid'] = $monitoringData['click_id'];

                if (!empty($monitoringData['advertiser_id'])) {
                    $advertiserId = $monitoringData['advertiser_id'];
                    $saveData['advertiser_id'] = $monitoringData['advertiser_id'];
                    $saveData['back_url'] = $monitoringData['callback'];
                }
            }
        } else if (!empty($params['is_capitalization']) && $params['type'] == 1) {
            // 抖音资产化
            $token = config('tiktok.capitalization.token');
            $url = config('tiktok.capitalization.url');
            $timestamp = time();
            $rand = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
            shuffle($rand);

            $nonceArray = array_slice($rand, 0, 4);
            $nonce = implode('', $nonceArray);

            $collect = [(string)$token, (string)$nonce, (string)$timestamp];
            usort($collect, 'strcmp');
            $signature = sha1(implode('', $collect));

            if (!empty($params['clue_token'])) {
                $body = [
                    'clue_token' => $params['clue_token'],
                    'open_id' => $openId,
                    'event_type' => '0'
                ];

                $requestData = json_encode($body);

                $url = $url . '?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;
                $result = Common::curlRequest($url, 'POST', $requestData, ['Content-Type : application/json']);
                $saveData['clickid'] = $params['clue_token'];
            }

            if (!empty($params['promotion_id'])) {
                $saveData['advertiser_id'] = $params['promotion_id'];
            } else if (!empty($params['ad_id'])) {
                $saveData['advertiser_id'] = $params['ad_id'];
            }

            // 获取客户端IP和ua
            if (!empty($_SERVER['HTTP_USER_AGENT'])) {
                $isAndroid = strpos($_SERVER['HTTP_USER_AGENT'], 'Android');
                if ($isAndroid) {
                    // Android
                    $regx = '/Build(.*?) /is';
                    preg_match($regx, $_SERVER['HTTP_USER_AGENT'], $match);

                    $userAgent = $match[1];
                } else {
                    // iOS
                    $regx = '/\((.*?)\)/';
                    preg_match($regx, $_SERVER['HTTP_USER_AGENT'], $match);
                    $userAgent = $match[1];
                }
                $saveData['ua'] = $userAgent ? strtoupper(str_replace(' ', '', $userAgent)) : '';
                $saveData['ip'] = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $_SERVER['HTTP_CLIENT_IP'];
            }

        } else if ($ip && $ua) {
            $saveData['ip'] = $ip;
            $saveData['ua'] = $ua;

            $monitoringData = $redis->get(md5($ip.$ua.$params['link_id']));

            if (empty($monitoringData)) {
                // 第二方案
                $monitoringData = $redis->get(md5($ua.$params['link_id']));
            }

            if ($monitoringData) {

                $monitoringData = json_decode($monitoringData, true);
                if (!empty($monitoringData['advertiser_id'])) {
                    $saveData['advertiser_id'] = $monitoringData['advertiser_id'];
                    $advertiserId = $monitoringData['advertiser_id'];
                }

                if (!empty($monitoringData['clickid'])) {
                    $saveData['clickid'] = $monitoringData['clickid'];
                    $clickid = $monitoringData['clickid'];

                    if (!empty($params['type']) && $params['type'] == 2) {
                        // 快手激活回传
                        $eventTime = Common::msectime();
                        $url = 'http://ad.partner.gifshow.com/track/activate?callback='.$clickid.'&event_type=1&event_time='.$eventTime;
                        $result = Common::curlRequest($url, 'GET');
                    } else {
                        // 抖音激活回传
                        $url = 'https://analytics.oceanengine.com/api/v2/conversion';
                        $requestData = [
                            'event_type' => 'active',
                            'context' => [
                                'ad' => [
                                    'callback' => $monitoringData['clickid']
                                ]
                            ],
                            'timestamp' => Common::msectime()
                        ];
                        $requestData = json_encode($requestData);
                        $result = Common::curlRequest($url, 'POST', $requestData, ['Content-Type : application/json']);
                    }
                }
            }
        }

        $uid = $this->model->edit($saveData);
        return [
            'uid' => $uid,
            'link_id' => $params['link_id'],
            'official_account_id' => !empty($userInfo) ? $userInfo['official_account_id'] : $linkData['official_account_id'],
            'sign_time' => !empty($userInfo) ? $userInfo['sign_time'] : null,
            'official_account_open_id' => !empty($userInfo) ? $userInfo['official_account_open_id'] : null,
            'interpolate_id' => !empty($userInfo) ? $userInfo['interpolate_id'] : null,
            'user_name' => empty($userInfo['user_name']) ? '' : $userInfo['user_name'],
            'avatar' => empty($userInfo['avatar']) ? '' : $userInfo['avatar'],
            'status' => !empty($userInfo['status']) ? $userInfo['status'] : 0,
            'is_delete' => !empty($userInfo['is_delete']) ? $userInfo['is_delete'] : 0,
            'ip' => $ip,
            'ua' => $ua,
            'advertiser_id' => $advertiserId,
            'clickid' => $clickid,
        ];
    }

    // 直接进入小程序
    public function appletEnter(array $params, string $openId)
    {
        $userInfo = $this->model->getInfoByOpenId($openId, 'id, is_delete, applet_id, sign_time, official_account_id, user_name, avatar, status, link_id');

        if (!$userInfo) {
            $appletData = $this->appletModel->getInfoByWhere(['app_id' => $params['app_id']]);
            $officialAccountsData = $this->officialAccountsModel->getInfoByWhere(['applet_id' => $appletData['id'], 'is_default' => 1], 'id');
            $saveData = [
                'open_id' => $openId,
                'applet_id' => $appletData['id'],
                'last_login_time' => time(),
                'register_date' => date('Ymd'),
                'created_at' => time(),
                'source' => 2,
                'mobile_system' => empty($params['mobile_system']) ? null : $params['mobile_system'],
            ];
            if ($officialAccountsData) {
                $saveData['official_account_id'] = $officialAccountsData['id'];
            }
        } else {

            $saveData = [
                'id' => $userInfo['id'],
                'last_login_time' => time(),
                'updated_at' => time(),
                'mobile_system' => empty($params['mobile_system']) ? null : $params['mobile_system'],
            ];

            if (empty($userInfo['official_account_id'])) {
                $officialAccountsData = $this->officialAccountsModel->getInfoByWhere(['applet_id' => $userInfo['applet_id'], 'is_default' => 1], 'id');
                if ($officialAccountsData) {
                    $saveData['official_account_id'] = $officialAccountsData['id'];
                }
            } else {
                $officialAccountsData = $this->officialAccountsModel->getInfoByWhere(['id' => $userInfo['official_account_id']], 'id');
            }
        }

        $uid = $this->model->edit($saveData);
        $data = [
            'uid' => $uid,
            'link_id' => !empty($userInfo['link_id']) ? $userInfo['link_id'] : '',
            'sign_time' => !empty($userInfo) ? $userInfo['sign_time'] : null,
            'official_account_open_id' => !empty($userInfo['official_account_open_id']) ? $userInfo['official_account_open_id'] : null,
            'interpolate_id' => !empty($userInfo['interpolate_id']) ? $userInfo['interpolate_id'] : null,
            'user_name' => !empty($userInfo['user_name']) ? $userInfo['user_name'] : '',
            'avatar' => !empty($userInfo['avatar']) ? $userInfo['avatar'] : '',
            'status' => !empty($userInfo['status']) ? $userInfo['status'] : 0,
            'is_delete' => !empty($userInfo['is_delete']) ? $userInfo['is_delete'] : 0
        ];

        if ($officialAccountsData) {
            $data['official_account_id'] = $officialAccountsData['id'];
        } else {
            $data['official_account_id'] = '';
        }

        return $data;
    }

    // 添加微信授权获取的用户信息
    public function setWechatUserInfo($params)
    {
        $redis = Cache::store('redis')->handler();
        $uid = $redis->get($params['token']);

        $id = $this->model->edit([
            'id' => $uid,
            'user_name' => $params['user_name'],
            'avatar' => $params['avatar']
        ]);

        return $id ? true : false;
    }
}